home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume11 / mtools / part02 < prev    next >
Encoding:
Text File  |  1987-08-27  |  42.4 KB  |  1,811 lines

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v11i024:  MS-DOS disk tools for Unix, Part02/02
  5. Message-ID: <1248@uunet.UU.NET>
  6. Date: 28 Aug 87 13:09:40 GMT
  7. Sender: Unknown@uunet.UU.NET
  8. Organization: UUNET Communications Services, Arlington, VA
  9. Lines: 1799
  10. Approved: rs@uunet.UU.NET
  11.  
  12. Submitted-by: uiucdcs!fthood!egray@harvard.harvard.edu
  13. Posting-number: Volume 11, Issue 24
  14. Archive-name: mtools/Part02
  15.  
  16. #! /bin/sh
  17. # This is a shell archive, meaning:
  18. # 1. Remove everything above the #! /bin/sh line.
  19. # 2. Save the resulting text in a file.
  20. # 3. Execute the file with /bin/sh (not csh) to create:
  21. #    mkentry.c
  22. #    mmd.c
  23. #    mrd.c
  24. #    mread.c
  25. #    mren.c
  26. #    mtype.c
  27. #    mwrite.c
  28. #    putfat.c
  29. #    search.c
  30. #    subdir.c
  31. #    unixname.c
  32. # This archive created: Thu Jul  9 22:35:45 1987
  33. export PATH; PATH=/bin:/usr/bin:$PATH
  34. echo shar: "extracting 'mkentry.c'" '(2497 characters)'
  35. if test -f 'mkentry.c'
  36. then
  37.     echo shar: "will not over-write existing file 'mkentry.c'"
  38. else
  39. sed 's/^X//' << \SHAR_EOF > 'mkentry.c'
  40. X/*
  41. X * mk_entry(), grow()
  42. X */
  43. X
  44. X#include <stdio.h>
  45. X#include <time.h>
  46. X#include "msdos.h"
  47. X
  48. Xextern int fd, dir_start, dir_len, clus_size, dir_entries;
  49. Xextern int dir_chain[25];
  50. X
  51. X/*
  52. X * Make a directory entry.  Builds a directory entry based on the
  53. X * name, attribute, starting cluster number, and size.  Returns a pointer
  54. X * to the directory structure.
  55. X */
  56. X
  57. Xstruct directory *
  58. Xmk_entry(filename, attr, fat, size)
  59. Xchar *filename;
  60. Xunsigned char attr;
  61. Xint fat;
  62. Xint size;
  63. X{
  64. X    long clock, time();
  65. X    int i;
  66. X    char *strncpy();
  67. X    static struct directory ndir;
  68. X    struct tm *now, *localtime();
  69. X    unsigned char hour, min_hi, min_low, sec;
  70. X    unsigned char year, month_hi, month_low, day;
  71. X
  72. X    time(&clock);
  73. X    now = localtime(&clock);
  74. X    strncpy(ndir.name, filename, 8);
  75. X    strncpy(ndir.ext, filename+8, 3);
  76. X    ndir.attr = attr;
  77. X    for (i=0; i<10; i++)
  78. X        ndir.reserved[i] = NULL;
  79. X    hour = now->tm_hour << 3;
  80. X    min_hi = now->tm_min >> 3;
  81. X    min_low = now->tm_min << 5;
  82. X    sec = 0;
  83. X    ndir.time[1] = hour + min_hi;
  84. X    ndir.time[0] = min_low + sec;
  85. X    year = (now->tm_year - 80) << 1;
  86. X    month_hi = (now->tm_mon+1) >> 3;
  87. X    month_low = (now->tm_mon+1) << 5;
  88. X    day = now->tm_mday;
  89. X    ndir.date[1] = year + month_hi;
  90. X    ndir.date[0] = month_low + day;
  91. X    ndir.start[1] = fat / 0x100;
  92. X    ndir.start[0] = fat % 0x100;
  93. X    ndir.size[3] = 0;        /* can't be THAT large */
  94. X    ndir.size[2] = size / 0x10000;
  95. X    ndir.size[1] = (size % 0x10000) / 0x100;
  96. X    ndir.size[0] = (size % 0x10000) % 0x100;
  97. X    return(&ndir);
  98. X}
  99. X
  100. X/*
  101. X * Make a subdirectory grow in length.  Only subdirectories (not root) 
  102. X * may grow.  Returns a 0 on success or 1 on failure (disk full).
  103. X */
  104. X
  105. Xint
  106. Xgrow(fat)
  107. Xint fat;
  108. X{
  109. X    int i, next, last, getfat(), nextfat(), num, sector, buflen;
  110. X    char tbuf[1024];
  111. X    void perror(), exit();
  112. X
  113. X    last = nextfat(0);
  114. X    if (last == -1)
  115. X        return(1);
  116. X
  117. X    while (1) {
  118. X        next = getfat(fat);
  119. X        if (next == -1) {
  120. X            fprintf(stderr, "grow: FAT problem\n");
  121. X            exit(1);
  122. X        }
  123. X                    /* end of cluster chain */
  124. X        if (next >= 0xff8)
  125. X            break;
  126. X        fat = next;
  127. X    }
  128. X                    /* mark the end of the chain */
  129. X    putfat(fat, last);
  130. X    putfat(last, 0xfff);
  131. X                    /* zero the buffer */
  132. X    buflen = clus_size * MSECSIZ;
  133. X    for (i=0; i<buflen; i++)
  134. X        tbuf[i] = NULL;
  135. X
  136. X                    /* write the cluster */
  137. X    sector = (last - 2) * clus_size + dir_start + dir_len;
  138. X    move(sector);
  139. X    if (write(fd, tbuf, buflen) != buflen) {
  140. X        perror("grow: write");
  141. X        exit(1);
  142. X    }
  143. X                    /* fix up the globals.... */
  144. X    num = dir_entries / 16;
  145. X    dir_entries += clus_size * 16;
  146. X    dir_chain[num] = sector;
  147. X    if (clus_size == 2)
  148. X        dir_chain[num+1] = sector +1;
  149. X    return(0);
  150. X}
  151. SHAR_EOF
  152. if test 2497 -ne "`wc -c < 'mkentry.c'`"
  153. then
  154.     echo shar: "error transmitting 'mkentry.c'" '(should have been 2497 characters)'
  155. fi
  156. fi
  157. echo shar: "extracting 'mmd.c'" '(3672 characters)'
  158. if test -f 'mmd.c'
  159. then
  160.     echo shar: "will not over-write existing file 'mmd.c'"
  161. else
  162. sed 's/^X//' << \SHAR_EOF > 'mmd.c'
  163. X/*
  164. X * Make a MSDOS sub directory
  165. X *
  166. X * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  167. X * ...!ihnp4!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  168. X *                     Directorate of Engineering & Housing
  169. X *                     Environmental Management Office
  170. X *                     Fort Hood, TX 76544-5057
  171. X */
  172. X
  173. X#include <stdio.h>
  174. X#include "msdos.h"
  175. X
  176. Xint fd;                /* the file descriptor for the floppy */
  177. Xint dir_start;            /* starting sector for directory */
  178. Xint dir_len;            /* length of directory (in sectors) */
  179. Xint dir_entries;        /* number of directory entries */
  180. Xint dir_chain[25];        /* chain of sectors in directory */
  181. Xint clus_size;            /* cluster size (in sectors) */
  182. Xint fat_len;            /* length of FAT table (in sectors) */
  183. Xint num_clus;            /* number of available clusters */
  184. Xunsigned char *fatbuf;        /* the File Allocation Table */
  185. Xchar *mcwd;            /* the Current Working Directory */
  186. X
  187. Xmain(argc, argv)
  188. Xint argc;
  189. Xchar *argv[];
  190. X{
  191. X    int entry, slot, fat, dot, subdir();
  192. X    char *filename, *newfile, *fixname(), *strncpy(), *unixname();
  193. X    char *getpath(), *pathname, tname[9], text[4], *fixed;
  194. X    void exit();
  195. X    struct directory *dir, *search(), *mk_entry();
  196. X
  197. X    if (init(2)) {
  198. X        fprintf(stderr, "mmd: Cannot initialize diskette\n");
  199. X        exit(1);
  200. X    }
  201. X                    /* only 1 directory ! */
  202. X    if (argc != 2) {
  203. X        fprintf(stderr, "Usage: mmd <MSDOS directory>\n");
  204. X        exit(1);
  205. X    }
  206. X    fixed = fixname(argv[1]);
  207. X    filename = unixname(fixed, fixed+8);
  208. X    pathname = getpath(argv[1]);
  209. X    if (strcmp(fixed+8, "   ")) {
  210. X        fprintf(stderr, "mmd: Directory names cannot have extensions\n");
  211. X        exit(1);
  212. X    }
  213. X    if (subdir(pathname))
  214. X        exit(1);
  215. X                    /* see if exists and get slot */
  216. X    slot = -1;
  217. X    dot = 0;
  218. X    for (entry=0; entry<dir_entries; entry++) {
  219. X        dir = search(entry);
  220. X                    /* if empty */
  221. X        if (dir->name[0] == NULL) {
  222. X            if (slot < 0)
  223. X                slot = entry;
  224. X            break;
  225. X        }
  226. X                    /* if erased */
  227. X        if (dir->name[0] == 0xe5) {
  228. X            if (slot < 0)
  229. X                slot = entry;
  230. X            continue;
  231. X        }
  232. X                    /* if not a directory */
  233. X        if (!(dir->attr & 0x10))
  234. X            continue;
  235. X        strncpy(tname, dir->name, 8);
  236. X        strncpy(text, dir->ext, 3);
  237. X        newfile = unixname(tname, text);
  238. X                    /* save the 'dot' directory info */
  239. X        if (!strcmp(".", newfile))
  240. X            dot = dir->start[1]*0x100 + dir->start[0];
  241. X
  242. X        if (!strcmp(filename, newfile)) {
  243. X            fprintf(stderr, "mmd: Directory '%s' already exists\n", filename);
  244. X            exit(1);
  245. X        }
  246. X    }
  247. X                    /* no '.' entry means root directory */
  248. X    if (dot == 0 && slot < 0) {
  249. X        printf(stderr, "mmd: No directory slots\n");
  250. X        exit(1);
  251. X    }
  252. X                    /* make the directory grow */
  253. X    if (dot && slot < 0) {
  254. X        if (grow(dot)) {
  255. X            fprintf(stderr, "mmd: Disk full\n");
  256. X            exit(1);
  257. X        }
  258. X                    /* first slot in 'new' directory */
  259. X        slot = entry;
  260. X    }
  261. X    fat = nextfat(0);
  262. X    if (fat == -1) {
  263. X        fprintf(stderr, "mmd: Disk full\n");
  264. X        exit(1);
  265. X    }
  266. X                    /* make directory entry */
  267. X    dir = mk_entry(fixed, 0x10, fat, 0);
  268. X    if (dir != NULL) {
  269. X        writedir(slot, dir);
  270. X                    /* write the cluster */
  271. X        putfat(fat, 0xfff);
  272. X        putcluster(fat, dot);
  273. X    }
  274. X                    /* write FAT sectors */
  275. X    writefat();
  276. X    close(fd);
  277. X    exit(0);
  278. X}
  279. X
  280. Xputcluster(dot, dot_dot)        /* write the cluster */
  281. Xint dot;
  282. Xint dot_dot;
  283. X{
  284. X    long start;
  285. X    void exit(), perror();
  286. X    int buflen;
  287. X    static struct directory dirs[32];
  288. X    struct directory *mk_entry();
  289. X
  290. X    start = (dot - 2)*clus_size + dir_start + dir_len;
  291. X    move(start);
  292. X
  293. X    buflen = clus_size * MSECSIZ;
  294. X                    /* make the '.' and '..' entries */    
  295. X    dirs[0] = *mk_entry(".          ", 0x10, dot, 0);
  296. X    dirs[1] = *mk_entry("..         ", 0x10, dot_dot, 0);
  297. X
  298. X    if (write(fd, (char *) &dirs[0], buflen) != buflen) {
  299. X        perror("putcluster: write");
  300. X        exit(1);
  301. X    }
  302. X    return;
  303. X}
  304. X
  305. Xint
  306. Xnextfat(last)                /* returns next free cluster */
  307. Xint last;
  308. X{
  309. X    static int i;
  310. X
  311. X    for (i=last+1; i<num_clus+2; i++) {
  312. X        if (!getfat(i))
  313. X            return(i);
  314. X    }
  315. X    return(-1);
  316. X}
  317. SHAR_EOF
  318. if test 3672 -ne "`wc -c < 'mmd.c'`"
  319. then
  320.     echo shar: "error transmitting 'mmd.c'" '(should have been 3672 characters)'
  321. fi
  322. fi
  323. echo shar: "extracting 'mrd.c'" '(3148 characters)'
  324. if test -f 'mrd.c'
  325. then
  326.     echo shar: "will not over-write existing file 'mrd.c'"
  327. else
  328. sed 's/^X//' << \SHAR_EOF > 'mrd.c'
  329. X/*
  330. X * Delete a MSDOS sub directory
  331. X *
  332. X * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  333. X * ...!ihnp4!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  334. X *                     Directorate of Engineering & Housing
  335. X *                     Environmental Management Office
  336. X *                     Fort Hood, TX 76544-5057
  337. X */
  338. X
  339. X#include <stdio.h>
  340. X#include "msdos.h"
  341. X
  342. Xint fd;                /* the file descriptor for the floppy */
  343. Xint dir_start;            /* starting sector for directory */
  344. Xint dir_len;            /* length of directory (in sectors) */
  345. Xint dir_entries;        /* number of directory entries */
  346. Xint dir_chain[25];        /* chain of sectors in directory */
  347. Xint clus_size;            /* cluster size (in sectors) */
  348. Xint fat_len;            /* length of FAT table (in sectors) */
  349. Xint num_clus;            /* number of available clusters */
  350. Xunsigned char *fatbuf;        /* the File Allocation Table */
  351. Xchar *mcwd;            /* the Current Working Directory */
  352. X
  353. Xmain(argc, argv)
  354. Xint argc;
  355. Xchar *argv[];
  356. X{
  357. X    int ismatch, entry, start, isempty();
  358. X    char *filename, *newfile, text[4], tname[9], *getname();
  359. X    char *strncpy(), *pathname, *getpath(), *unixname();
  360. X    void exit();
  361. X    struct directory *dir, *search();
  362. X
  363. X    if (init(2)) {
  364. X        fprintf(stderr, "mrd: Cannot initialize diskette\n");
  365. X        exit(1);
  366. X    }
  367. X                    /* only 1 directory ! */
  368. X    if (argc != 2) {
  369. X        fprintf(stderr, "Usage: mrd <MSDOS directory>\n");
  370. X        exit(1);
  371. X    }
  372. X
  373. X    filename = getname(argv[1]);
  374. X    pathname = getpath(argv[1]);
  375. X    if (subdir(pathname))
  376. X        exit(1);
  377. X    ismatch = 0;
  378. X    for (entry=0; entry<dir_entries; entry++) {
  379. X        dir = search(entry);
  380. X                    /* if empty */
  381. X        if (dir->name[0] == NULL)
  382. X            break;
  383. X                    /* if erased */
  384. X        if (dir->name[0] == 0xe5)
  385. X            continue;
  386. X                    /* if not dir */
  387. X        if (!(dir->attr & 0x10))
  388. X            continue;
  389. X        strncpy(tname, dir->name, 8);
  390. X        strncpy(text, dir->ext, 3);
  391. X        newfile = unixname(tname, text);
  392. X        if (!strcmp(newfile, filename)) {
  393. X            start = dir->start[1]*0x100 + dir->start[0];
  394. X            if (!isempty(start)) {
  395. X                fprintf(stderr, "mrd: Directory '%s' is not empty\n", filename);
  396. X                exit(1);
  397. X            }
  398. X            if (!start) {
  399. X                fprintf(stderr, "mrd: Can't remove root directory\n");
  400. X                exit(1);
  401. X            }
  402. X            zapit(start);
  403. X            dir->name[0] = 0xe5;
  404. X            writedir(entry, dir);
  405. X            ismatch = 1;
  406. X        }
  407. X    }
  408. X    if (!ismatch) {
  409. X        fprintf(stderr, "mrd: Directory '%s' not found\n", filename);
  410. X        exit(1);
  411. X    }
  412. X                    /* update the FAT sectors */
  413. X    writefat();
  414. X    close(fd);
  415. X    exit(0);
  416. X}
  417. X
  418. X/*
  419. X * See if directory is empty.  Returns 1 if empty, 0 if not.  Can't use
  420. X * subdir() and search() as it would clobber the globals.
  421. X */
  422. X
  423. Xint
  424. Xisempty(fat)
  425. Xint fat;
  426. X{
  427. X    int i, next, buflen, sector, getfat();
  428. X    unsigned char tbuf[1024];
  429. X    void perror(), exit();
  430. X
  431. X    while (1) {
  432. X        sector = (fat-2)*clus_size + dir_start + dir_len;
  433. X        move(sector);
  434. X        buflen = clus_size * MSECSIZ;
  435. X        if (read(fd, tbuf, buflen) != buflen) {
  436. X            perror("isempty: read");
  437. X            exit(1);
  438. X        }
  439. X                    /* check first character of name */
  440. X        for (i=0; i<MSECSIZ; i+=MDIRSIZ) {
  441. X            if (tbuf[i] == '.')
  442. X                continue;
  443. X            if (tbuf[i] != NULL && tbuf[i] != 0xe5)
  444. X                return(0);
  445. X        }
  446. X                    /* get next cluster number */
  447. X        next = getfat(fat);
  448. X        if (next == -1) {
  449. X            fprintf(stderr, "isempty: FAT problem\n");
  450. X            exit(1);
  451. X        }
  452. X                    /* end of cluster chain */
  453. X        if (next >= 0xff8)
  454. X            break;
  455. X        fat = next;
  456. X    }
  457. X    return(1);
  458. X}
  459. SHAR_EOF
  460. if test 3148 -ne "`wc -c < 'mrd.c'`"
  461. then
  462.     echo shar: "error transmitting 'mrd.c'" '(should have been 3148 characters)'
  463. fi
  464. fi
  465. echo shar: "extracting 'mread.c'" '(4523 characters)'
  466. if test -f 'mread.c'
  467. then
  468.     echo shar: "will not over-write existing file 'mread.c'"
  469. else
  470. sed 's/^X//' << \SHAR_EOF > 'mread.c'
  471. X/*
  472. X * Read (copy) a MSDOS file to Unix
  473. X *
  474. X * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  475. X * ...!ihnp4!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  476. X *                     Directorate of Engineering & Housing
  477. X *                     Environmental Management Office
  478. X *                     Fort Hood, TX 76544-5057
  479. X */
  480. X
  481. X#include <stdio.h>
  482. X#include <sys/types.h>
  483. X#include <sys/stat.h>
  484. X#include "msdos.h"
  485. X
  486. Xint fd;                /* the file descriptor for the floppy */
  487. Xint dir_start;            /* starting sector for directory */
  488. Xint dir_len;            /* length of directory (in sectors) */
  489. Xint dir_entries;        /* number of directory entries */
  490. Xint dir_chain[25];        /* chain of sectors in directory */
  491. Xint clus_size;            /* cluster size (in sectors) */
  492. Xint fat_len;            /* length of FAT table (in sectors) */
  493. Xint num_clus;            /* number of available clusters */
  494. Xunsigned char *fatbuf;        /* the File Allocation Table */
  495. Xchar *mcwd;            /* the Current Working Directory */
  496. X
  497. Xlong size;
  498. Xlong current;
  499. Xint textmode = 0;
  500. Xint nowarn = 0;
  501. X
  502. Xmain(argc, argv)
  503. Xint argc;
  504. Xchar *argv[];
  505. X{
  506. X    extern int optind;
  507. X    extern char *optarg;
  508. X    int fat, i, ismatch, entry, subdir(), single, c, oops;
  509. X    char *filename, *newfile, text[4], tname[9], *getname(), *unixname();
  510. X    char *strncpy(), *pathname, *getpath(), *target, *tmp, *malloc();
  511. X    char *strcat(), *strcpy();
  512. X    void perror(), exit();
  513. X    struct directory *dir, *search();
  514. X    struct stat stbuf;
  515. X
  516. X    if (init(0)) {
  517. X        fprintf(stderr, "mread: Cannot initialize diskette\n");
  518. X        exit(1);
  519. X    }
  520. X                    /* get command line options */
  521. X    oops = 0;
  522. X    while ((c = getopt(argc, argv, "tn")) != EOF) {
  523. X        switch(c) {
  524. X            case 't':
  525. X                textmode = 1;
  526. X                break;
  527. X            case 'n':
  528. X                nowarn = 1;
  529. X                break;
  530. X            default:
  531. X                oops = 1;
  532. X                break;
  533. X        }
  534. X    }
  535. X
  536. X    if (oops || (argc - optind) < 2) {
  537. X        fprintf(stderr, "Usage: mread [-t|-n] <MSDOS file> <Unix file>\n");
  538. X        fprintf(stderr, "    or mread [-t|-n] <MSDOS file> [<MSDOS files...>] <Unix directory>\n");
  539. X        exit(1);
  540. X    }
  541. X                    /* only 1 file to copy... */
  542. X    single = 1;
  543. X    target = argv[argc-1];
  544. X                    /* ...unless last arg is a directory */
  545. X    if (!stat(target, &stbuf)) {
  546. X        if (stbuf.st_mode & 040000)
  547. X            single = 0;    
  548. X    }
  549. X
  550. X    for (i=optind; i<argc-1; i++) {
  551. X        filename = getname(argv[i]);
  552. X        pathname = getpath(argv[i]);
  553. X        if (subdir(pathname))
  554. X            continue;
  555. X        ismatch = 0;
  556. X        for (entry=0; entry<dir_entries; entry++) {
  557. X            dir = search(entry);
  558. X                    /* if empty */
  559. X            if (dir->name[0] == NULL)
  560. X                break;
  561. X                    /* if erased */
  562. X            if (dir->name[0] == 0xe5)
  563. X                continue;
  564. X                    /* if dir or volume lable */
  565. X            if ((dir->attr & 0x10) || (dir->attr & 0x08))
  566. X                continue;
  567. X            strncpy(tname, dir->name, 8);
  568. X            strncpy(text, dir->ext, 3);
  569. X            newfile = unixname(tname, text);
  570. X            fat = dir->start[1]*0x100 + dir->start[0];
  571. X            size = dir->size[2]*0x10000 + dir->size[1]*0x100 + dir->size[0];
  572. X                    /* if single file */
  573. X            if (single) {
  574. X                if (!strcmp(newfile, filename)) {
  575. X                    readit(fat, target);
  576. X                    ismatch = 1;
  577. X                    break;
  578. X                }
  579. X            }
  580. X                    /* if multiple files */
  581. X            else {
  582. X                if (match(newfile, filename)) {
  583. X                    printf("Copying %s\n", newfile);
  584. X                    tmp = malloc(strlen(target)+1+strlen(newfile)+1);
  585. X                    strcpy(tmp, target);
  586. X                    strcat(tmp, "/");
  587. X                    strcat(tmp, newfile);
  588. X                    readit(fat, tmp);
  589. X                    ismatch = 1;
  590. X                }
  591. X            }
  592. X        }
  593. X        if (!ismatch) {
  594. X            fprintf(stderr, "mread: File '%s' not found\n", filename);
  595. X            continue;
  596. X        }
  597. X    }
  598. X    close(fd);
  599. X    exit(0);
  600. X}
  601. X
  602. Xreadit(fat, target)
  603. Xint fat;
  604. Xchar *target;
  605. X{
  606. X    char ans[10];
  607. X    void exit();
  608. X    FILE *fp;
  609. X
  610. X    current = 0L;
  611. X    if (!nowarn) {
  612. X        if (!access(target, 0)) {
  613. X            while (1) {
  614. X                printf("File '%s' exists, overwrite (y/n) ? ", target);
  615. X                gets(ans);
  616. X                if (ans[0] == 'n' || ans[0] == 'N')
  617. X                    return;
  618. X                if (ans[0] == 'y' || ans[0] == 'Y')
  619. X                    break;
  620. X            }
  621. X        }
  622. X    }
  623. X
  624. X    if (!(fp = fopen(target, "w"))) {
  625. X        fprintf(stderr, "mread: Can't open '%s' for write\n", target);
  626. X        return;
  627. X    }
  628. X
  629. X    while (1) {
  630. X        getcluster(fat, fp);
  631. X                    /* get next cluster number */
  632. X        fat = getfat(fat);
  633. X        if (fat == -1) {
  634. X            fprintf(stderr, "mread: FAT problem\n");
  635. X            exit(1);
  636. X        }
  637. X                    /* end of cluster chain */
  638. X        if (fat >= 0xff8)
  639. X            break;
  640. X    }
  641. X    fclose(fp);
  642. X    return;
  643. X}
  644. X
  645. Xgetcluster(num, fp)            /* read a cluster */
  646. Xint num;
  647. XFILE *fp;
  648. X{
  649. X    int i, buflen, start;
  650. X    void exit(), perror();
  651. X    char buf[1024];
  652. X
  653. X    start = (num - 2)*clus_size + dir_start + dir_len;
  654. X    move(start);
  655. X
  656. X    buflen = clus_size * MSECSIZ;
  657. X    if (read(fd, buf, buflen) != buflen) {
  658. X        perror("getcluster: read");
  659. X        exit(1);
  660. X    }
  661. X                    /* stop at size not EOF marker */
  662. X    for (i=0; i<buflen; i++) {
  663. X        current++;
  664. X        if (current > size) 
  665. X            break;
  666. X        if (textmode && buf[i] == '\r')
  667. X            continue;
  668. X        fputc(buf[i], fp);
  669. X    }
  670. X    return;
  671. X}
  672. SHAR_EOF
  673. if test 4523 -ne "`wc -c < 'mread.c'`"
  674. then
  675.     echo shar: "error transmitting 'mread.c'" '(should have been 4523 characters)'
  676. fi
  677. fi
  678. echo shar: "extracting 'mren.c'" '(2628 characters)'
  679. if test -f 'mren.c'
  680. then
  681.     echo shar: "will not over-write existing file 'mren.c'"
  682. else
  683. sed 's/^X//' << \SHAR_EOF > 'mren.c'
  684. X/*
  685. X * Rename an existing MSDOS file
  686. X *
  687. X * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  688. X * ...!ihnp4!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  689. X *                     Directorate of Engineering & Housing
  690. X *                     Environmental Management Office
  691. X *                     Fort Hood, TX 76544-5057
  692. X */
  693. X
  694. X#include <stdio.h>
  695. X#include "msdos.h"
  696. X
  697. Xint fd;                /* the file descriptor for the floppy */
  698. Xint dir_start;            /* starting sector for directory */
  699. Xint dir_len;            /* length of directory (in sectors) */
  700. Xint dir_entries;        /* number of directory entries */
  701. Xint dir_chain[25];        /* chain of sectors in directory */
  702. Xint clus_size;            /* cluster size (in sectors) */
  703. Xint fat_len;            /* length of FAT table (in sectors) */
  704. Xint num_clus;            /* number of available clusters */
  705. Xunsigned char *fatbuf;        /* the File Allocation Table */
  706. Xchar *mcwd;            /* the Current Working Directory */
  707. X
  708. Xmain(argc, argv)
  709. Xint argc;
  710. Xchar *argv[];
  711. X{
  712. X    int entry, ismatch, subdir(), nogo, isdir();
  713. X    char *filename, *newfile, *fixname(), *strncpy(), *unixname();
  714. X    char *getpath(), *pathname, tname[9], text[4], *getname(), *target;
  715. X    char *new, ans[10], *temp, *strcpy();
  716. X    void exit();
  717. X    struct directory *dir, *search();
  718. X
  719. X    if (init(2)) {
  720. X        fprintf(stderr, "mren: Cannot initialize diskette\n");
  721. X        exit(1);
  722. X    }
  723. X    if (argc != 3) {
  724. X        fprintf(stderr, "Usage: mren <MSDOS source file> <MSDOS target file>\n");
  725. X        exit(1);
  726. X    }
  727. X    filename = getname(argv[1]);
  728. X    pathname = getpath(argv[1]);
  729. X    if (subdir(pathname))
  730. X        exit(1);
  731. X
  732. X    temp = getname(argv[2]);
  733. X    target = fixname(argv[2]);
  734. X    if (isdir(filename) && strcmp(target+8, "   ")) {
  735. X        strcpy(target+8, "   ");
  736. X        fprintf(stderr, "mren: Directory names may not have extentions\n");
  737. X    }
  738. X    new = unixname(target, target+8);
  739. X    nogo = 0;
  740. X                    /* the name supplied may be altered */
  741. X    if (strcmp(temp, new)) {
  742. X        while (!nogo) {
  743. X            printf("Do you accept '%s' as the new file name (y/n) ? ", new);
  744. X            gets(ans);
  745. X            if (ans[0] == 'y' || ans[0] == 'Y')
  746. X                break;
  747. X            if (ans[0] == 'n' || ans[0] == 'N')
  748. X                nogo = 1;
  749. X        }
  750. X    }
  751. X    if (nogo)
  752. X        exit(0);
  753. X                    /* see if exists and do it */
  754. X    ismatch = 0;
  755. X    for (entry=0; entry<dir_entries; entry++) {
  756. X        dir = search(entry);
  757. X                    /* if empty */
  758. X        if (dir->name[0] == NULL)
  759. X            break;
  760. X                    /* if erased */
  761. X        if (dir->name[0] == 0xe5)
  762. X            continue;
  763. X                    /* you may rename a directory */
  764. X        strncpy(tname, dir->name, 8);
  765. X        strncpy(text, dir->ext, 3);
  766. X        newfile = unixname(tname, text);
  767. X        if (!strcmp(filename, newfile)) {
  768. X            ismatch = 1;
  769. X            strncpy(dir->name, target, 8);
  770. X            strncpy(dir->ext, target+8, 3);
  771. X            writedir(entry, dir);
  772. X        }
  773. X    }
  774. X    if (!ismatch) {
  775. X        fprintf(stderr, "mren: File '%s' not found\n", filename);
  776. X        exit(1);
  777. X    }
  778. X    close(fd);
  779. X    exit(0);
  780. X}
  781. SHAR_EOF
  782. if test 2628 -ne "`wc -c < 'mren.c'`"
  783. then
  784.     echo shar: "error transmitting 'mren.c'" '(should have been 2628 characters)'
  785. fi
  786. fi
  787. echo shar: "extracting 'mtype.c'" '(3364 characters)'
  788. if test -f 'mtype.c'
  789. then
  790.     echo shar: "will not over-write existing file 'mtype.c'"
  791. else
  792. sed 's/^X//' << \SHAR_EOF > 'mtype.c'
  793. X/*
  794. X * Display contents of a MSDOS file
  795. X *
  796. X * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  797. X * ...!ihnp4!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  798. X *                     Directorate of Engineering & Housing
  799. X *                     Environmental Management Office
  800. X *                     Fort Hood, TX 76544-5057
  801. X */
  802. X
  803. X#include <stdio.h>
  804. X#include "msdos.h"
  805. X
  806. Xint fd;                /* the file descriptor for the floppy */
  807. Xint dir_start;            /* starting sector for directory */
  808. Xint dir_len;            /* length of directory (in sectors) */
  809. Xint dir_entries;        /* number of directory entries */
  810. Xint dir_chain[25];        /* chain of sectors in directory */
  811. Xint clus_size;            /* cluster size (in sectors) */
  812. Xint fat_len;            /* length of FAT table (in sectors) */
  813. Xint num_clus;            /* number of available clusters */
  814. Xunsigned char *fatbuf;        /* the File Allocation Table */
  815. Xchar *mcwd;            /* the Current Working Directory */
  816. X
  817. Xlong size;
  818. Xlong current;
  819. Xstripmode = 0;
  820. Xtextmode = 0;
  821. X
  822. Xmain(argc, argv)
  823. Xint argc;
  824. Xchar *argv[];
  825. X{
  826. X    extern int optind;
  827. X    extern char *optarg;
  828. X    int fat, i, ismatch, entry, subdir(), c, oops;
  829. X    char *filename, *newfile, text[4], tname[9], *getname(), *unixname();
  830. X    char *strncpy(), *pathname, *getpath();
  831. X    void exit();
  832. X    struct directory *dir, *search();
  833. X
  834. X    if (init(0)) {
  835. X        fprintf(stderr, "mtype: Cannot initialize diskette\n");
  836. X        exit(1);
  837. X    }
  838. X                    /* get command line options */
  839. X    oops = 0;
  840. X    while ((c = getopt(argc, argv, "st")) != EOF) {
  841. X        switch(c) {
  842. X            case 's':
  843. X                stripmode = 1;
  844. X                break;
  845. X            case 't':
  846. X                textmode = 1;
  847. X                break;
  848. X            default:
  849. X                oops = 1;
  850. X                break;
  851. X        }
  852. X    }
  853. X
  854. X    if (oops || (argc - optind) < 1) {
  855. X        fprintf(stderr, "Usage: mtype [-s|-t] <MSDOS file> [<MSDOS files...>]\n");
  856. X        exit(1);
  857. X    }
  858. X
  859. X    for (i=optind; i<argc; i++) {
  860. X        filename = getname(argv[i]);
  861. X        pathname = getpath(argv[i]);
  862. X        if (subdir(pathname))
  863. X            continue;
  864. X        ismatch = 0;
  865. X        for (entry=0; entry<dir_entries; entry++) {
  866. X            dir = search(entry);
  867. X                    /* if empty */
  868. X            if (dir->name[0] == NULL)
  869. X                break;
  870. X                    /* if erased */
  871. X            if (dir->name[0] == 0xe5)
  872. X                continue;
  873. X                    /* if dir or volume lable */
  874. X            if ((dir->attr & 0x10) || (dir->attr & 0x08))
  875. X                continue;
  876. X            strncpy(tname, dir->name, 8);
  877. X            strncpy(text, dir->ext, 3);
  878. X            newfile = unixname(tname, text);
  879. X                    /* see it if matches the pattern */
  880. X            if (match(newfile, filename)) {
  881. X                fat = dir->start[1]*0x100 + dir->start[0];
  882. X                size = dir->size[2]*0x10000 + dir->size[1]*0x100 + dir->size[0];
  883. X                readit(fat);
  884. X                ismatch = 1;
  885. X            }
  886. X        }
  887. X        if (!ismatch) {
  888. X            fprintf(stderr, "mtype: File '%s' not found\n", filename);
  889. X            continue;
  890. X        }
  891. X    }
  892. X    close(fd);
  893. X    exit(0);
  894. X}
  895. X
  896. Xreadit(fat)
  897. Xint fat;
  898. X{
  899. X    current = 0L;
  900. X
  901. X    while (1) {
  902. X        getcluster(fat);
  903. X                    /* get next cluster number */
  904. X        fat = getfat(fat);
  905. X        if (fat == -1) {
  906. X            fprintf(stderr, "mtype: FAT problem\n");
  907. X            exit(1);
  908. X        }
  909. X                    /* end of cluster chain */
  910. X        if (fat >= 0xff8)
  911. X            break;
  912. X    }
  913. X    return;
  914. X}
  915. X
  916. Xgetcluster(num)                /* read a cluster */
  917. Xint num;
  918. X{
  919. X    int i, buflen, start;
  920. X    void exit(), perror();
  921. X    char buf[1024];
  922. X
  923. X    start = (num - 2)*clus_size + dir_start + dir_len;
  924. X    move(start);
  925. X
  926. X    buflen = clus_size * MSECSIZ;
  927. X    if (read(fd, buf, buflen) != buflen) {
  928. X        perror("getcluster: read");
  929. X        exit(1);
  930. X    }
  931. X                    /* stop at size not EOF marker */
  932. X    for (i=0; i<buflen; i++) {
  933. X        current++;
  934. X        if (current > size) 
  935. X            break;
  936. X        if (textmode & buf[i] == '\r')
  937. X            continue;
  938. X        if (stripmode)
  939. X            putchar(buf[i] & 0x7f);
  940. X        else
  941. X            putchar(buf[i]);
  942. X    }
  943. X    return;
  944. X}
  945. SHAR_EOF
  946. if test 3364 -ne "`wc -c < 'mtype.c'`"
  947. then
  948.     echo shar: "error transmitting 'mtype.c'" '(should have been 3364 characters)'
  949. fi
  950. fi
  951. echo shar: "extracting 'mwrite.c'" '(7067 characters)'
  952. if test -f 'mwrite.c'
  953. then
  954.     echo shar: "will not over-write existing file 'mwrite.c'"
  955. else
  956. sed 's/^X//' << \SHAR_EOF > 'mwrite.c'
  957. X/*
  958. X * Write (copy) a Unix file to MSDOS
  959. X *
  960. X * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  961. X * ...!ihnp4!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  962. X *                     Directorate of Engineering & Housing
  963. X *                     Environmental Management Office
  964. X *                     Fort Hood, TX 76544-5057
  965. X */
  966. X
  967. X#include <stdio.h>
  968. X#include <sys/types.h>
  969. X#include <sys/stat.h>
  970. X#include "msdos.h"
  971. X
  972. Xint fd;                /* the file descriptor for the floppy */
  973. Xint dir_start;            /* starting sector for directory */
  974. Xint dir_len;            /* length of directory (in sectors) */
  975. Xint dir_entries;        /* number of directory entries */
  976. Xint dir_chain[25];        /* chain of sectors in directory */
  977. Xint clus_size;            /* cluster size (in sectors) */
  978. Xint fat_len;            /* length of FAT table (in sectors) */
  979. Xint num_clus;            /* number of available clusters */
  980. Xunsigned char *fatbuf;        /* the File Allocation Table */
  981. Xchar *mcwd;            /* the Current Working Directory */
  982. X
  983. Xint full = 0;
  984. Xint textmode = 0;
  985. Xint nowarn = 0;
  986. Xint filesize;
  987. X
  988. Xmain(argc, argv)
  989. Xint argc;
  990. Xchar *argv[];
  991. X{
  992. X    extern int optind;
  993. X    extern char *optarg;
  994. X    int i, entry, ismatch, nogo, slot, start, dot, subdir(), single;
  995. X    int isdir(), root, c, oops;
  996. X    char *filename, *newfile, tname[9], text[4], *fixname(), *getname();
  997. X    char *unixname(), ans[10], *strncpy(), *pathname, *getpath(), *fixed;
  998. X    char *tmp, *malloc(), *strcat(), *strcpy();
  999. X    void exit();
  1000. X    struct directory *dir, *search(), *writeit();
  1001. X
  1002. X    if (init(2)) {
  1003. X        fprintf(stderr, "mwrite: Cannot initialize diskette\n");
  1004. X        exit(1);
  1005. X    }
  1006. X                    /* get command line options */
  1007. X    oops = 0;
  1008. X    while ((c = getopt(argc, argv, "tn")) != EOF) {
  1009. X        switch(c) {
  1010. X            case 't':
  1011. X                textmode = 1;
  1012. X                break;
  1013. X            case 'n':
  1014. X                nowarn = 1;
  1015. X                break;
  1016. X            default:
  1017. X                oops = 1;
  1018. X                break;
  1019. X        }
  1020. X    }
  1021. X
  1022. X    if (oops || (argc - optind) < 2) {
  1023. X        fprintf(stderr, "Usage: mwrite [-t|-n] <Unix file> <MSDOS file>\n");
  1024. X        fprintf(stderr, "    or mwrite [-t|-n] <Unix file> [<Unix files...>] <MSDOS directory>\n");
  1025. X        exit(1);
  1026. X    }
  1027. X    root = 0;
  1028. X    if (!strcmp(argv[argc-1], "/") || !strcmp(argv[argc-1], "\\"))
  1029. X        root = 1;
  1030. X    filename = getname(argv[argc-1]);
  1031. X    pathname = getpath(argv[argc-1]);
  1032. X                    /* test if path is ok first */
  1033. X    if (subdir(pathname))
  1034. X        exit(1);
  1035. X                    /* test if last argv is a dir */
  1036. X    if (isdir(filename) || root) {
  1037. X        if (!strlen(pathname)) {
  1038. X                    /* don't alter the presence or */
  1039. X                    /* absence of a leading separator */
  1040. X            tmp = malloc(strlen(filename)+1);
  1041. X            strcpy(tmp, filename);
  1042. X        }
  1043. X        else {
  1044. X            tmp = malloc(strlen(pathname)+1+strlen(filename)+1);
  1045. X            strcpy(tmp, pathname);
  1046. X            strcat(tmp, "/");
  1047. X            strcat(tmp, filename);
  1048. X        }
  1049. X                    /* subdir is not recursive */
  1050. X        subdir(tmp);
  1051. X        single = 0;
  1052. X    }
  1053. X    else
  1054. X        single = 1;
  1055. X
  1056. X    for (i=optind; i<argc-1; i++) {
  1057. X        if (single) {
  1058. X            fixed = fixname(argv[argc-1]);
  1059. X            filename = unixname(fixed, fixed+8);
  1060. X        }
  1061. X        else {
  1062. X            fixed = fixname(argv[i]);
  1063. X            filename = unixname(fixed, fixed+8);
  1064. X            printf("Copying %s\n", filename);
  1065. X        }
  1066. X                    /* see if exists and get slot */
  1067. X        ismatch = 0;
  1068. X        slot = -1;
  1069. X        dot = 0;
  1070. X        nogo = 0;
  1071. X        for (entry=0; entry<dir_entries; entry++) {
  1072. X            dir = search(entry);
  1073. X                    /* is empty */
  1074. X            if (dir->name[0] == NULL) {
  1075. X                if (slot < 0)
  1076. X                    slot = entry;
  1077. X                break;
  1078. X            }
  1079. X                    /* is erased */
  1080. X            if (dir->name[0] == 0xe5) {
  1081. X                if (slot < 0)
  1082. X                    slot = entry;
  1083. X                continue;
  1084. X            }
  1085. X            strncpy(tname, dir->name, 8);
  1086. X            strncpy(text, dir->ext, 3);
  1087. X            newfile = unixname(tname, text);
  1088. X                    /* save the '.' entry info */
  1089. X            if ((dir->attr & 0x10) && !strcmp(".", newfile)) {
  1090. X                dot = dir->start[1]*0x100 + dir->start[0];
  1091. X                continue;
  1092. X            }
  1093. X                    /* is dir or volume lable */
  1094. X            if ((dir->attr & 0x10) || (dir->attr & 0x08))
  1095. X                continue;
  1096. X                    /* if file exists, delete it first */
  1097. X            if (!strcmp(filename, newfile)) {
  1098. X                ismatch = 1;
  1099. X                start = dir->start[1]*0x100 + dir->start[0];
  1100. X                if (nowarn) {
  1101. X                    zapit(start);
  1102. X                    dir->name[0] = 0xe5;
  1103. X                    writedir(entry, dir);
  1104. X                    if (slot < 0)
  1105. X                        slot = entry;
  1106. X                } else {
  1107. X                    while (1) {
  1108. X                        printf("File '%s' exists, overwrite (y/n) ? ", filename);
  1109. X                        gets(ans);
  1110. X                        if (ans[0] == 'n' || ans[0] == 'N') {
  1111. X                            nogo = 1;
  1112. X                            break;
  1113. X                        }
  1114. X                        if (ans[0] == 'y' || ans[0] == 'Y') {
  1115. X                            zapit(start);
  1116. X                            dir->name[0] = 0xe5;
  1117. X                            writedir(entry, dir);
  1118. X                            if (slot < 0)
  1119. X                                slot = entry;
  1120. X                            break;
  1121. X                        }
  1122. X                    }
  1123. X                }
  1124. X            }
  1125. X            if (ismatch)
  1126. X                break;
  1127. X        }
  1128. X        if (nogo)        /* chickened out... */
  1129. X            continue;
  1130. X                    /* no '.' entry means root directory */
  1131. X        if (dot == 0 && slot < 0) {
  1132. X            printf(stderr, "mwrite: No directory slots\n");
  1133. X            exit(1);
  1134. X        }
  1135. X                    /* make the directory grow */
  1136. X        if (dot && slot < 0) {
  1137. X            if (grow(dot)) {
  1138. X                fprintf(stderr, "mwrite: Disk full\n");
  1139. X                exit(1);
  1140. X            }
  1141. X                    /* first entry in 'new' directory */
  1142. X            slot = entry;
  1143. X        }
  1144. X                    /* write the file */
  1145. X        dir = writeit(fixed, argv[i]);
  1146. X        if (dir != NULL)
  1147. X            writedir(slot, dir);
  1148. X
  1149. X        if (full) {
  1150. X            fprintf(stderr, "mwrite: Disk Full\n");
  1151. X            break;
  1152. X        }
  1153. X        if (single)
  1154. X            break;
  1155. X    }
  1156. X                    /* write FAT sectors */
  1157. X    writefat();
  1158. X    close(fd);
  1159. X    exit(0);
  1160. X}
  1161. X
  1162. Xstruct directory *
  1163. Xwriteit(fixed, path)
  1164. Xchar *fixed;
  1165. Xchar *path;
  1166. X{
  1167. X    FILE *fp;
  1168. X    int size, fat, firstfat, oldfat, nextfat(), putcluster(), putfat();
  1169. X    struct directory *mk_entry();
  1170. X    static struct directory *dir;
  1171. X    struct stat stbuf;
  1172. X
  1173. X    if (stat(path, &stbuf) < 0) {
  1174. X        fprintf(stderr, "mwrite: Can't stat '%s'\n", path);
  1175. X        return(NULL);
  1176. X    }
  1177. X    filesize = stbuf.st_size;
  1178. X    if (!(fp = fopen(path, "r"))) {
  1179. X        fprintf(stderr, "mwrite: Can't open '%s' for read\n", path);
  1180. X        return(NULL);
  1181. X    }
  1182. X    size = 0;
  1183. X    firstfat = nextfat(0);
  1184. X    if (firstfat == -1) {
  1185. X        full = 1;
  1186. X        return(NULL);
  1187. X    }
  1188. X    fat = firstfat;
  1189. X    while (1) {
  1190. X        size += putcluster(fat, fp);
  1191. X        if (size >= filesize) {
  1192. X            putfat(fat, 0xfff);
  1193. X            break;
  1194. X        }
  1195. X        oldfat = fat;
  1196. X                    /* get next free cluster */
  1197. X        fat = nextfat(oldfat);
  1198. X        if (fat == -1) {
  1199. X            putfat(oldfat, 0xfff);
  1200. X            full = 1;
  1201. X            break;
  1202. X        }
  1203. X        putfat(oldfat, fat);
  1204. X    }
  1205. X    fclose(fp);
  1206. X    dir = mk_entry(fixed, 0, firstfat, size);
  1207. X    return(dir);
  1208. X}
  1209. X
  1210. Xint
  1211. Xputcluster(num, fp)            /* write to a cluster */
  1212. Xint num;
  1213. XFILE *fp;
  1214. X{
  1215. X    long start;
  1216. X    void exit(), perror();
  1217. X    int buflen, c;
  1218. X    static int current;
  1219. X    char tbuf[1024];
  1220. X
  1221. X    start = (num - 2)*clus_size + dir_start + dir_len;
  1222. X    move(start);
  1223. X
  1224. X    buflen = clus_size * MSECSIZ;
  1225. X                    /* '\n' to '\r\n' translation */
  1226. X    if (textmode) {
  1227. X        current = 0;
  1228. X        while (current < buflen) {
  1229. X            if ((c = fgetc(fp)) == EOF) {
  1230. X                    /* put a file EOF marker */
  1231. X                tbuf[current] = 0x1a;
  1232. X                break;
  1233. X            }
  1234. X            if (c == '\n') {
  1235. X                tbuf[current++] = '\r';
  1236. X                if (current == buflen)
  1237. X                    break;
  1238. X                tbuf[current++] = '\n';
  1239. X                    /* make the file appear larger */
  1240. X                filesize++;
  1241. X            }
  1242. X            else 
  1243. X                tbuf[current++] = c;
  1244. X        }
  1245. X    }
  1246. X    else {
  1247. X        if ((current = fread(tbuf, sizeof(char), buflen, fp)) < 0) {
  1248. X            perror("putcluster: fread");
  1249. X            exit(1);
  1250. X        }
  1251. X                    /* all files get an EOF marker */
  1252. X        if (current != buflen) 
  1253. X            tbuf[current+1] = 0x1a;
  1254. X    }
  1255. X    
  1256. X    if (write(fd, tbuf, buflen) != buflen) {
  1257. X        perror("putcluster: write");
  1258. X        exit(1);
  1259. X    }
  1260. X    return(current);
  1261. X}
  1262. X
  1263. Xint
  1264. Xnextfat(last)                /* returns next free cluster */
  1265. Xint last;
  1266. X{
  1267. X    static int i;
  1268. X
  1269. X    for (i=last+1; i<num_clus+2; i++) {
  1270. X        if (!getfat(i))
  1271. X            return(i);
  1272. X    }
  1273. X    return(-1);
  1274. X}
  1275. SHAR_EOF
  1276. if test 7067 -ne "`wc -c < 'mwrite.c'`"
  1277. then
  1278.     echo shar: "error transmitting 'mwrite.c'" '(should have been 7067 characters)'
  1279. fi
  1280. fi
  1281. echo shar: "extracting 'putfat.c'" '(3118 characters)'
  1282. if test -f 'putfat.c'
  1283. then
  1284.     echo shar: "will not over-write existing file 'putfat.c'"
  1285. else
  1286. sed 's/^X//' << \SHAR_EOF > 'putfat.c'
  1287. X/*
  1288. X * putfat(), writedir(), zapit(), writefat()
  1289. X */
  1290. X
  1291. X#include <stdio.h>
  1292. X#include "msdos.h"
  1293. X#undef DUP_FAT
  1294. X
  1295. Xextern int fd, fat_len, dir_chain[25];
  1296. Xextern unsigned char *fatbuf;
  1297. X
  1298. X/*
  1299. X * Puts a code into the FAT table.  Is the opposite of getfat().  No
  1300. X * sanity checking is done on the code.  Returns a 1 on error.
  1301. X */
  1302. X
  1303. Xint
  1304. Xputfat(num, code)
  1305. Xint num;
  1306. Xunsigned int code;
  1307. X{
  1308. X/*
  1309. X *    |    byte n     |   byte n+1    |   byte n+2    |
  1310. X *    |0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
  1311. X *    | | | | | | | | | | | | | | | | | | | | | | | | |
  1312. X *    |  n.0  |  n.5  | n+1.0 | n+1.5 | n+2.0 | n+2.5 |
  1313. X *        \_____  \____   \______/________/_____   /
  1314. X *          ____\______\________/   _____/  ____\_/
  1315. X *         /     \      \          /       /     \
  1316. X *    | n+1.5 |  n.0  |  n.5  | n+2.0 | n+2.5 | n+1.0 |
  1317. X *    |      FAT entry k      |    FAT entry k+1      |
  1318. X */
  1319. X    int start;
  1320. X                    /* which bytes contain the entry */
  1321. X    start = num * 3 / 2;
  1322. X    if (start < 0 || start+1 > (fat_len * MSECSIZ))
  1323. X        return(1);
  1324. X                    /* (odd) not on byte boundary */
  1325. X    if (num % 2) {
  1326. X        *(fatbuf+start) = (*(fatbuf+start) & 0x0f) + ((code << 4) & 0xf0);
  1327. X        *(fatbuf+start+1) = (code >> 4) & 0xff;
  1328. X    }
  1329. X                    /* (even) on byte boundary */
  1330. X    else {
  1331. X        *(fatbuf+start) = code & 0xff;
  1332. X        *(fatbuf+start+1) = (*(fatbuf+start+1) & 0xf0) + ((code >> 8) & 0x0f);
  1333. X    }
  1334. X    return(0);
  1335. X}
  1336. X
  1337. X/*
  1338. X * Write a directory entry.  The first argument is the directory entry
  1339. X * number to write to.  The second is a pointer to the directory itself.
  1340. X * All errors are fatal.
  1341. X */
  1342. X
  1343. Xwritedir(num, dir)
  1344. Xint num;
  1345. Xstruct directory *dir;
  1346. X{
  1347. X    int skip, entry;
  1348. X    void exit(), perror();
  1349. X    static struct directory dirs[16];
  1350. X                    /* which sector */
  1351. X    skip = dir_chain[num / 16];
  1352. X
  1353. X    move(skip);
  1354. X                    /* read the sector */
  1355. X    if (read(fd, (char *) &dirs[0], MSECSIZ) != MSECSIZ) {
  1356. X        perror("writedir: read");
  1357. X        exit(1);
  1358. X    }
  1359. X                    /* which entry in sector */
  1360. X    entry = num % 16;
  1361. X                    /* copy the structure */
  1362. X    dirs[entry] = *dir;
  1363. X    move(skip);
  1364. X                    /* write the sector */
  1365. X    if (write(fd, (char *) &dirs[0], MSECSIZ) != MSECSIZ) {
  1366. X        perror("writedir: write");
  1367. X        exit(1);
  1368. X    }
  1369. X    return;
  1370. X}
  1371. X
  1372. X/*
  1373. X * Remove a string of FAT entries (delete the file).  The argument is
  1374. X * the beginning of the string.  Does not consider the file length, so
  1375. X * if FAT is corrupted, watch out!  All errors are fatal.
  1376. X */
  1377. X
  1378. Xzapit(fat)
  1379. Xint fat;
  1380. X{
  1381. X    int next;
  1382. X
  1383. X    while (1) {
  1384. X                    /* get next cluster number */
  1385. X        next = getfat(fat);
  1386. X                    /* mark current cluster as empty */
  1387. X        if (putfat(fat, 0) || next == -1) {
  1388. X            fprintf(stderr, "zapit: FAT problem\n");
  1389. X            exit(1);
  1390. X        }
  1391. X        if (next >= 0xff8)
  1392. X            break;
  1393. X        fat = next;
  1394. X    }
  1395. X    return;
  1396. X}
  1397. X
  1398. X/*
  1399. X * Write the FAT table to the disk.  Up to now the FAT manipulation has
  1400. X * been done in memory.  All errors are fatal.  (Might not be too smart
  1401. X * to wait till the end of the program to write the table.  Oh well...)
  1402. X */
  1403. X
  1404. Xwritefat()
  1405. X{
  1406. X    int buflen;
  1407. X
  1408. X    move(1);
  1409. X    buflen = fat_len * MSECSIZ;
  1410. X    if (write(fd, fatbuf, buflen) != buflen) {
  1411. X        perror("writefat: write");
  1412. X        exit(1);
  1413. X    }
  1414. X#ifdef DUP_FAT
  1415. X                    /* the duplicate FAT table */
  1416. X    if (write(fd, fatbuf, buflen) != buflen) {
  1417. X        perror("writefat: write");
  1418. X        exit(1);
  1419. X    }
  1420. X#endif DUP_FAT
  1421. X    return;
  1422. X}
  1423. SHAR_EOF
  1424. if test 3118 -ne "`wc -c < 'putfat.c'`"
  1425. then
  1426.     echo shar: "error transmitting 'putfat.c'" '(should have been 3118 characters)'
  1427. fi
  1428. fi
  1429. echo shar: "extracting 'search.c'" '(1075 characters)'
  1430. if test -f 'search.c'
  1431. then
  1432.     echo shar: "will not over-write existing file 'search.c'"
  1433. else
  1434. sed 's/^X//' << \SHAR_EOF > 'search.c'
  1435. X/*
  1436. X * Search and extract a directory structure.  The argument is the
  1437. X * relative directory entry number (no sanity checking).  It returns a
  1438. X * pointer to the directory structure at that location.  Attempts to
  1439. X * optimize by trying to determine if the buffer needs to be re-read.
  1440. X * A call to writedir() will scribble on the real buffer, so watch out!
  1441. X */
  1442. X
  1443. X#include <stdio.h>
  1444. X#include "msdos.h"
  1445. X                /* dir_chain contains the list of sectors */
  1446. X                /* that make up the current directory */
  1447. Xextern int fd, dir_chain[25];
  1448. X
  1449. Xstruct directory *
  1450. Xsearch(num)
  1451. Xint num;
  1452. X{
  1453. X    int skip, entry;
  1454. X    void exit(), perror();
  1455. X    static int last;
  1456. X    static struct directory dirs[16];
  1457. X
  1458. X                    /* first call disables optimzation */
  1459. X    if (num == 0)
  1460. X        last = 0;
  1461. X                    /* which sector */
  1462. X    skip = dir_chain[num / 16];
  1463. X                    /* don't read it if same sector */
  1464. X    if (skip != last) {
  1465. X        move(skip);
  1466. X                    /* read the sector */
  1467. X        if (read(fd, (char *) &dirs[0], MSECSIZ) != MSECSIZ) {
  1468. X            perror("mread: read");
  1469. X            exit(1);
  1470. X        }
  1471. X    }
  1472. X    last = skip;
  1473. X                    /* which entry in sector */
  1474. X    entry = num % 16;
  1475. X    return(&dirs[entry]);
  1476. X}
  1477. SHAR_EOF
  1478. if test 1075 -ne "`wc -c < 'search.c'`"
  1479. then
  1480.     echo shar: "error transmitting 'search.c'" '(should have been 1075 characters)'
  1481. fi
  1482. fi
  1483. echo shar: "extracting 'subdir.c'" '(3854 characters)'
  1484. if test -f 'subdir.c'
  1485. then
  1486.     echo shar: "will not over-write existing file 'subdir.c'"
  1487. else
  1488. sed 's/^X//' << \SHAR_EOF > 'subdir.c'
  1489. X/*
  1490. X * subdir(), getdir(), get_chain(), reset_dir()
  1491. X */
  1492. X
  1493. X#include <stdio.h>
  1494. X#include "msdos.h"
  1495. X
  1496. Xextern int dir_chain[25], dir_start, dir_len, dir_entries, clus_size;
  1497. Xextern char *mcwd;
  1498. Xstatic char *lastpath;
  1499. X
  1500. X/*
  1501. X * Parse the path names of a sub directory.  Both '/' and '\' are
  1502. X * valid separators.  However, the use of '\' will force the operator
  1503. X * to use quotes in the command line to protect '\' from the shell.
  1504. X * Returns 1 on error.  Attempts to optimize by remembering the last
  1505. X * path it parsed
  1506. X */
  1507. X
  1508. Xsubdir(name)
  1509. Xchar *name;
  1510. X{
  1511. X    char *s, *tmp, *path, *malloc(), *strchr(), *strcpy(), *strcat();
  1512. X    static int code;
  1513. X    int getdir();
  1514. X                    /* if full pathname */
  1515. X    if (*name == '/' || *name == '\\') {
  1516. X        tmp = malloc(strlen(name)+1);
  1517. X        strcpy(tmp, name);
  1518. X    }
  1519. X                    /* if relative to MCWD */
  1520. X    else {
  1521. X        if (!strlen(name)) {
  1522. X            tmp = malloc(strlen(mcwd)+1);
  1523. X            strcpy(tmp, mcwd);
  1524. X        }
  1525. X        else {
  1526. X            tmp = malloc(strlen(mcwd)+1+strlen(name)+1);
  1527. X            strcpy(tmp, mcwd);
  1528. X            strcat(tmp, "/");
  1529. X            strcat(tmp, name);
  1530. X        }
  1531. X    }
  1532. X                    /* if paths are same, do nothing */
  1533. X    if (!strcmp(tmp, lastpath))
  1534. X        return(0);
  1535. X                    /* not recursive, start at root */
  1536. X    reset_dir();
  1537. X    lastpath = malloc(strlen(tmp)+1);
  1538. X    strcpy(lastpath, tmp);
  1539. X                    /* zap the leading separator */
  1540. X    if (*tmp == '\\' || *tmp == '/')
  1541. X        tmp++;
  1542. X    for (s = tmp; *s; ++s) {
  1543. X        if (*s == '\\' || *s == '/') {
  1544. X            path = tmp;
  1545. X            *s = NULL;
  1546. X            if (getdir(path))
  1547. X                return(1);
  1548. X            tmp = s+1;
  1549. X        }
  1550. X    }
  1551. X    code = getdir(tmp);
  1552. X    return(code);
  1553. X}
  1554. X
  1555. X/*
  1556. X * Find the directory and get the starting cluster.  A null directory
  1557. X * is ok.  Returns a 1 on error.
  1558. X */
  1559. X
  1560. Xint
  1561. Xgetdir(path)
  1562. Xchar *path;
  1563. X{
  1564. X    int entry, start, get_chain();
  1565. X    char *newname, *unixname(), *strncpy(), name[9], ext[4];
  1566. X    struct directory *dir, *search();
  1567. X
  1568. X                    /* nothing required */
  1569. X    if (*path == NULL)
  1570. X        return(0);
  1571. X
  1572. X    for (entry=0; entry<dir_entries; entry++) {
  1573. X        dir = search(entry);
  1574. X                    /* if empty */
  1575. X        if (dir->name[0] == NULL)
  1576. X            break;
  1577. X                    /* if erased */
  1578. X        if (dir->name[0] == 0xe5)
  1579. X            continue;
  1580. X                    /* skip if not a directory */
  1581. X        if (!(dir->attr & 0x10))
  1582. X            continue;
  1583. X        strncpy(name, dir->name, 8);
  1584. X        name[8] = NULL;
  1585. X        strncpy(ext, dir->ext, 3);
  1586. X        ext[3] = NULL;
  1587. X        newname = unixname(name, ext);
  1588. X        if (!strcmp(newname, path)) {
  1589. X            start = dir->start[1]*0x100 + dir->start[0];
  1590. X                    /* if '..' pointing to root */
  1591. X            if (!start && !strcmp(path, "..")) {
  1592. X                reset_dir();
  1593. X                return(0);
  1594. X            }
  1595. X                    /* fill in the directory chain */
  1596. X            dir_entries = get_chain(start) * 16;
  1597. X            return(0);
  1598. X        }
  1599. X    }
  1600. X                    /* if '.' or '..', must be root */
  1601. X    if (!strcmp(path, ".") || !strcmp(path, "..")) {
  1602. X        reset_dir();
  1603. X        return(0);
  1604. X    }
  1605. X    fprintf(stderr, "Path component '%s' is not a directory\n", path);
  1606. X    return(1);
  1607. X}
  1608. X
  1609. X/*
  1610. X * Fill in the global variable dir_chain.  Argument is the starting
  1611. X * cluster number.  Info, in this variable is used by search() to 
  1612. X * scan a directory.  An arbitrary limit of 25 sectors is placed, this
  1613. X * equates to 400 entries.  Returns the number of sectors in the chain.
  1614. X */
  1615. X
  1616. Xint
  1617. Xget_chain(num)                /* fill the directory chain */
  1618. Xint num;
  1619. X{
  1620. X    int next;
  1621. X    static int i;
  1622. X    void exit();
  1623. X
  1624. X    i = 0;
  1625. X    while (1) {
  1626. X        dir_chain[i] = (num - 2)*clus_size + dir_start + dir_len;
  1627. X                    /* sectors, not clusters! */
  1628. X        if (clus_size == 2) {
  1629. X            dir_chain[i+1] = dir_chain[i] + 1;
  1630. X            i++;
  1631. X        }
  1632. X        i++;
  1633. X        if (i >= 25) {
  1634. X            fprintf(stderr, "get_chain: directory too large\n");
  1635. X            exit(1);
  1636. X        }
  1637. X                    /* get next cluster number */
  1638. X        next = getfat(num);
  1639. X        if (next == -1) {
  1640. X            fprintf(stderr, "get_chain: FAT problem\n");
  1641. X            exit(1);
  1642. X        }
  1643. X                    /* end of cluster chain */
  1644. X        if (next >= 0xff8) {
  1645. X            break;
  1646. X        }
  1647. X        num = next;
  1648. X    }
  1649. X    return(i);
  1650. X}
  1651. X
  1652. X/* 
  1653. X * Reset the global variable dir_chain to the root directory.
  1654. X */
  1655. X
  1656. Xreset_dir()
  1657. X{
  1658. X    int i;
  1659. X
  1660. X    for (i=0; i<dir_len; i++)
  1661. X        dir_chain[i] = dir_start + i;
  1662. X    dir_entries = dir_len * 16;
  1663. X                    /* disable subdir() optimization */
  1664. X    lastpath = "\0";
  1665. X    return;
  1666. X}
  1667. SHAR_EOF
  1668. if test 3854 -ne "`wc -c < 'subdir.c'`"
  1669. then
  1670.     echo shar: "error transmitting 'subdir.c'" '(should have been 3854 characters)'
  1671. fi
  1672. fi
  1673. echo shar: "extracting 'unixname.c'" '(2293 characters)'
  1674. if test -f 'unixname.c'
  1675. then
  1676.     echo shar: "will not over-write existing file 'unixname.c'"
  1677. else
  1678. sed 's/^X//' << \SHAR_EOF > 'unixname.c'
  1679. X/*
  1680. X * unixname(), getname(), getpath()
  1681. X */
  1682. X
  1683. X#include <stdio.h>
  1684. X#include <ctype.h>
  1685. X
  1686. X/*
  1687. X * Get rid of spaces in a MSDOS 'raw' name (one that has come from the
  1688. X * directory structure) so that it can be used for regular expression
  1689. X * matching with a unix file name.  Also used to 'unfix' a name that has
  1690. X * been altered by fixname().  Returns a pointer to the unix style name.
  1691. X */
  1692. X
  1693. Xchar *
  1694. Xunixname(name, ext)
  1695. Xchar *name;
  1696. Xchar *ext;
  1697. X{
  1698. X    static char *ans;
  1699. X    char *s, tname[9], text[4], *strcpy(), *strcat(), *malloc();
  1700. X    char *strchr(), *strncpy();
  1701. X
  1702. X    strncpy(tname, name, 8);
  1703. X    s = strchr(tname, ' ');
  1704. X    if (s != NULL)
  1705. X        *s = NULL;
  1706. X    tname[8] = NULL;
  1707. X
  1708. X    strncpy(text, ext, 3);
  1709. X    s = strchr(text, ' ');
  1710. X    if (s != NULL)
  1711. X        *s = NULL;
  1712. X    text[3] = NULL;
  1713. X
  1714. X    if (*text != NULL) {
  1715. X        ans = malloc(strlen(tname)+1+strlen(text)+1);
  1716. X        strcpy(ans, tname);
  1717. X        strcat(ans, ".");
  1718. X        strcat(ans, text);
  1719. X    }
  1720. X    else {
  1721. X        ans = malloc(strlen(tname)+1);
  1722. X        strcpy(ans, tname);
  1723. X    }
  1724. X    return(ans);
  1725. X}
  1726. X
  1727. X/*
  1728. X * Get name component of filename.  Translates name to upper case.  Returns
  1729. X * pointer to new name.  Could be NULL.
  1730. X */
  1731. X
  1732. Xchar *
  1733. Xgetname(name)
  1734. Xchar *name;
  1735. X{
  1736. X    char *s, *malloc(), *strcpy(), *strrchr();
  1737. X    static char *temp;
  1738. X
  1739. X    if (*name == NULL)
  1740. X        return(NULL);
  1741. X
  1742. X    temp = malloc(strlen(name)+1);
  1743. X    strcpy(temp, name);
  1744. X                
  1745. X    if (s = strrchr(temp, '/'))
  1746. X        temp = s+1;
  1747. X    if (s = strrchr(temp, '\\'))
  1748. X        temp = s+1;
  1749. X
  1750. X    for (s = temp; *s; ++s) {
  1751. X        if (islower(*s))
  1752. X            *s = toupper(*s);
  1753. X    }
  1754. X    return(temp);
  1755. X}
  1756. X
  1757. X/*
  1758. X * Get the path component of the filename.  Translates to upper case.
  1759. X * Returns pointer to path or NULL if no path exist.  Doesn't alter
  1760. X * leading separator, always strips trailing separator (unless it is the
  1761. X * path itself).
  1762. X */
  1763. X
  1764. Xchar *
  1765. Xgetpath(name)
  1766. Xchar *name;
  1767. X{
  1768. X    char *s, *s1, *malloc(), *strcpy(), *strrchr();
  1769. X    static char *temp;
  1770. X
  1771. X    if (*name == NULL)
  1772. X        return(NULL);
  1773. X
  1774. X    temp = malloc(strlen(name)+1);
  1775. X    strcpy(temp, name);
  1776. X
  1777. X    s = strrchr(temp, '/');
  1778. X    s1 = strrchr(temp, '\\');
  1779. X                    /* if both are NULL , no path */
  1780. X    if (s1 == s)
  1781. X        return(NULL);
  1782. X                    /* zap which ever is last separator */
  1783. X    if (s1 > s)
  1784. X        *s1 = NULL;
  1785. X    if (s > s1)
  1786. X        *s = NULL;
  1787. X                    /* translate to upper case */
  1788. X    for (s = temp; *s; ++s) {
  1789. X        if (islower(*s))
  1790. X            *s = toupper(*s);
  1791. X    }
  1792. X                    /* if null, put separator back */
  1793. X    if (!strlen(temp))
  1794. X        temp = "/";
  1795. X    return(temp);
  1796. X}
  1797. SHAR_EOF
  1798. if test 2293 -ne "`wc -c < 'unixname.c'`"
  1799. then
  1800.     echo shar: "error transmitting 'unixname.c'" '(should have been 2293 characters)'
  1801. fi
  1802. fi
  1803. exit 0
  1804. #    End of shell archive
  1805.  
  1806. -- 
  1807.  
  1808. Rich $alz
  1809. Cronus Project, BBN Labs            rsalz@bbn.com
  1810. Moderator, comp.sources.unix            sources@uunet.uu.net
  1811.